<?php


namespace App\Services\Algo;

use App\Interf\Calculable;
use TestingItemService;
use App\Models\LogHelper;

class PostpartumWeightRetentionTestingAlgo extends BaseTestingAlgo implements Calculable
{
    public $allAnswers;
    private $typeFourExpress;

    public function __construct($tid, $answerStr, $typeFourExpress = null)
    {

        parent::__construct($tid, $answerStr);
        $this->typeFourExpress = $typeFourExpress;
        $this->allAnswers = $this->convertAllAnswers();

    }

    public function calculate()
    {
        return $this->entrance($this->tid, $this->answers);

    }

    /**
     * 将拼装后的答案转换成字符串
     * @return string
     */
    public function resultToStr()
    {
        return $this->arrToStr($this->answers);
    }


    public function getAllAnswer()
    {
        return $this->answers;
    }

    /**
     * @param $tid
     * @param $answers
     * @return float|null
     */
    protected function entrance($tid, $answers)
    {
        $totalScore =null;
        return $totalScore;
    }




    protected function convertAllAnswers()
    {

        LogHelper::log('before calculate BMI=============>');
        LogHelper::log($this->answers);
        $TotalScore = [];
        LogHelper::log('this->typeFourExpress=============>');
        LogHelper::log($this->typeFourExpress);
        if ($this->typeFourExpress) {
            foreach ($this->typeFourExpress as $d) {
                if ($d['index'] == 19) {
                    array_push($TotalScore, $d);
                    break;
                }
            }
            $result = $this->fourTypeArray($TotalScore, $this->answers);
            foreach ($result as $v) {
                array_push($this->answers, $v);
            }
        }

        LogHelper::log('after calculate BMI grouping=============>');
        LogHelper::log($this->answers);
        $types = 6;
        $dymTypeData = TestingItemService::getItemsByQuestionType($this->tid, $types, '_SIX');

        if (count($dymTypeData) > 0) {
            foreach ($dymTypeData as $data) {
                if ($data['index'] == 20) {
                    $expressStr = $data['expression'];
                    $weight = $this->getSingleItemWeight($expressStr);

                    $obj['index'] = $data['index'];
                    $obj['answer'] = '';
                    $obj['weight'] = $weight;
                    array_push($this->answers, $obj);
                }

            }
        }


        LogHelper::log('before calculate totalScore=============>');
        LogHelper::log($this->answers);
        $TotalScore = [];
        LogHelper::log('this->typeFourExpress=============>');
        LogHelper::log($this->typeFourExpress);
        if ($this->typeFourExpress) {
            foreach ($this->typeFourExpress as $d) {
                if ($d['index'] != 19) {
                    array_push($TotalScore, $d);
                }
            }
            $result = $this->fourTypeArray($TotalScore, $this->answers);
            foreach ($result as $v) {
                array_push($this->answers, $v);
            }
        }

        LogHelper::log('after calculate judge=============>');
        LogHelper::log($this->answers);
        $types = 6;
        $dymTypeData = TestingItemService::getItemsByQuestionType($this->tid, $types, '_SIX');

        if (count($dymTypeData) > 0) {
            foreach ($dymTypeData as $data) {
                if ($data['index'] == 23) {
                    $expressStr = $data['expression'];
                    $weight = $this->getSingleItemWeights($expressStr);
                    $obj['index'] = $data['index'];
                    $obj['answer'] = '';
                    $obj['weight'] = $weight;
                    array_push($this->answers, $obj);
                }

            }
        }

        return $this->answers;
    }


    /**
     * 获取单个type为6的类型的权重
     */
    protected function getSingleItemWeights($expressStr)
    {

        $expressionList = $this->convertExpression($expressStr);
        $weight = 0;

        foreach ($expressionList as $exp) {

            $answerObj = $this->getAnswerObjByIndex($exp['index'], $this->answers);
            $answerObjs = $this->getAnswerObjByIndex($exp['index']+1, $this->answers);

            $replaceStr1 = '';
            switch ($exp['operate']) {
                case '@':
                    $replaceStr1 = $answerObj['weight'];
                    break;
                case '$':
                    $replaceStr1 = $answerObj['answer'];
                    break;
            }

            $search1 = $exp['operate'] . $exp['index'];

            $replaceStr2 = '';
            switch ($exp['operate']) {
                case '@':
                    $replaceStr2 = $answerObjs['weight'];
                    break;
                case '$':
                    $replaceStr2 = $answerObjs['answer'];
                    break;
            }
            $tempExp=$exp['index']+1;
            $search2 = $exp['operate'] . $tempExp;
            //首先替换表达式  $val=0<@23&&@23<4?1:0 中的@23，
            //同时下面的$val变量一定要与表达式中的$val保持一致，否则$val条件判断值取不到结果。

            $val = str_replace($search1, $replaceStr1, $exp['condition']);
            $val = str_replace($search2, $replaceStr2, $val);
            //通过php的eval函数计算php的表达式

            eval($val);

            if ($val) {
                //如果条件表达式条件成立则去权重。
                $weight = $exp['weight'];
                break;
            }
        }

         return $weight;
    }

    /**     
     * 获取单个type为6的类型的权重
     */
    protected function getSingleItemWeight($expressStr)
    {

        $expressionList = $this->convertExpression($expressStr);
        $weight = 0;

        foreach ($expressionList as $exp) {

            $answerObj = $this->getAnswerObjByIndex($exp['index'], $this->answers);

            $replaceStr = '';
            switch ($exp['operate']) {
                case '@':
                    $replaceStr = $answerObj['weight'];
                    break;
                case '$':
                    $replaceStr = $answerObj['answer'];
                    break;
            }

            $search = $exp['operate'] . $exp['index'];

            //首先替换表达式  $val=0<@23&&@23<4?1:0 中的@23，
            //同时下面的$val变量一定要与表达式中的$val保持一致，否则$val条件判断值取不到结果。
            $val = str_replace($search, $replaceStr, $exp['condition']);
            //通过php的eval函数计算php的表达式

            eval($val);
            if ($val) {
                //如果条件表达式条件成立则去权重。
                $weight = $exp['weight'];
                break;
            }
        }

        return $weight;
    }



    protected function convertExpression($expressionStr)
    {
        $arr = [];
        $expressions = explode("|||", $expressionStr);
        if (count($expressions) > 0) {
            foreach ($expressions as $e) {

                $data = explode('##', $e);
                $relateExp = $data[0];
                // 解析这种形式的表达式0<=$4&&$4<80:$4
                $condArr = explode(':', $relateExp);
                //如果不存在则构造一个
                $condition = $this->compactConditionStr($condArr[0]);
                $obj['condition'] = $condition;
                //拆分条件表达式中的所以和操作符号($和@)
                if ($operateObj = $this->compactOperateStr($condArr[0])) {
                    foreach ($operateObj as $key => $val) {
                        $obj[$key] = $val;
                    }
                } else {
                    $obj['index'] = -1;
                    $obj['operate'] = '';
                }
                $obj['weight'] = $data[1];
                array_push($arr, $obj);
            }
        }

        return $arr;
    }


    /**
     * 拆分操作表达式 形如@23或者$23这种
     * @param string $operateStr
     * @return array
     */
    protected function compactOperateStr($operateStr)
    {
        $obj = [];
        if (strpos("$operateStr", '@')) {
            $obj['operate'] = '@';
            $obj['index'] = (int)substr($operateStr, strpos("$operateStr", '@') + 1, 2);
        } elseif (strpos("$operateStr", '$')) {
            $obj['operate'] = '$';
            $obj['index'] = (int)substr($operateStr, strpos("$operateStr", '$') + 1, 1);
        }
        return $obj;
    }









}